#ifndef OCL_KERNEL_INCLUDED
#define OCL_KERNEL_INCLUDED 1

#include "../ocl/program.h"
#include "../ocl/buffer.h"

/*******************************************************************************
 *
 * cl_kernel wrappers
 *
 ******************************************************************************/

typedef struct
{
	cl_kernel handle;
	char     *FUNCTION_NAME;
	cl_uint   NUM_ARGS;
} ocl_kernel;

/** \brief Static initializer */
#define OCL_KERNEL_INIT { NULL, NULL, 0 }


int  ocl_kernel_load( ocl_kernel *kernel, ocl_program *program, const char *name );
void ocl_kernel_quit( ocl_kernel *kernel );


/*******************************************************************************
 *
 * setting arguments
 *
 ******************************************************************************/
int  ocl_kernel_set_arg( ocl_kernel *kernel, cl_uint arg_index, size_t arg_size, const void *arg_value );
int  ocl_kernel_set_arg_buffer( ocl_kernel *kernel, cl_uint arg_index, ocl_buffer *buffer );
int  ocl_kernel_set_arg_local(  ocl_kernel *kernel, cl_uint arg_index, size_t bytes );

#define OCL_KERNEL_SET_ARGS_INIT(kernel,ARG_INDEX,THE_RESULT) \
do { \
/* */	int            THE_RESULT    = 0; \
/* */	cl_uint        ARG_INDEX     = 0; \
/* */	int *        __the_result    = & THE_RESULT; \
/* */	cl_uint *    __the_arg_index = & ARG_INDEX;  \
/* */   ocl_kernel * __the_kernel = (kernel)


#define OCL_KERNEL_SET_ARG(TYPE,X)       do { if( (*__the_result) >= 0 ) (*__the_result) = ocl_kernel_set_arg( __the_kernel, (*__the_arg_index)++, sizeof(TYPE), &X); } while(0)
#define OCL_KERNEL_SET_ARG_BUFFER(NAME)  do { if( (*__the_result) >= 0 ) (*__the_result) = ocl_kernel_set_arg_buffer( __the_kernel, (*__the_arg_index)++, (NAME)); } while(0)

#define OCL_KERNEL_SET_ARGS_DONE() } while(0)

/*******************************************************************************
 *
 * specific information
 *
 ******************************************************************************/

/** \brief Specific CL_KERNEL_WORK_GROUP_SIZE.
 *
 *	\return CL_KERNEL_WORK_GROUP_SIZE>0 upon success, 0 upon failure.
 */
int ocl_get_kernel_work_group_size( const ocl_kernel *kernel, const ocl_device *device, size_t *wgs);


#endif

